// HttpServerHandler.java - Request handler for HttpServer.
//
// Copyright (C) 1999-2002  Smart Software Consulting
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//
// Smart Software Consulting
// 1688 Silverwood Court
// Danville, CA  94526-3079
// USA
//
// http://www.smartsc.com
//

package com.smartsc.http;

import java.io.IOException;
import java.net.Socket;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;

public class
HttpServerHandler
implements HttpStatusCodes, HttpReasonPhrases, HttpMethods, Runnable
{
	// Protected contructor
	protected
	HttpServerHandler( HttpServer server, Socket socket)
	throws HttpException
	{
		this.server = server;
		this.socket = socket;
	}

	protected
	boolean
	init()
	{
		boolean initOk = true;

		try
		{
			req = new HttpRequest( server, socket);
			res = new HttpResponse( server, req, socket);
		}
		catch( Exception e)
		{
			server.log( e);
			if( socket != null)
			{
				try { socket.close(); }
				catch( IOException ioe) {}
			}
			initOk = false;
		}

		return initOk;
	}

	public final
	void
	run()
	{
		// TODO handle "Keep-Alive"
		boolean initOk = init();

		if( initOk)
		{
			try
			{
				server.addHandler();
				req.parseRequest();
				String servletName = req.getServletName();
				RequestDispatcher rd = server.getNamedDispatcher( servletName );
				if( rd != null )
				{
					rd.forward( req, res );
					// Response has been closed.  Set res to null
					// so that closeConnection() will not re-close response.
					res = null;
				}
				else
				{
					if( notFoundHttpException == null )
					{
						notFoundHttpException =
							new HttpException( SC_NOT_FOUND, RP_NOT_FOUND );
					}
					throw notFoundHttpException;
				}
			}
			catch( HttpException he)
			{
				server.log( he);
				res.sendError(
					he.getStatusCode(),
					he.getReasonPhrase());
			}
			catch( ServletException se)
			{
				Throwable rootCause = se.getRootCause();
				if( rootCause instanceof HttpException )
				{
					HttpException he = (HttpException)rootCause;
					server.log( he );
					res.sendError(
						he.getStatusCode(),
						he.getReasonPhrase());
				}
				else
				{
					server.log( se );
					res.sendError(
						SC_INTERNAL_SERVER_ERROR,
						RP_INTERNAL_SERVER_ERROR);
				}
			}
			catch( Exception e)
			{
				server.log( e);
				res.sendError(
					SC_INTERNAL_SERVER_ERROR,
					RP_INTERNAL_SERVER_ERROR);
			}
			finally
			{
				closeConnection();
				server.removeHandler();
			}
		}
	}

	protected
	void
	closeConnection()
	{
		if( res != null)
		{
			try { res.close(); }
			catch( IOException ioe) {}
		}

		if( req != null)
		{
			try { req.close(); }
			catch( IOException ioe) {}
		}

		if( socket != null)
		{
			try { socket.close(); }
			catch( IOException ioe) {}
		}
	}
	private HttpServer server;
	private Socket socket;
	private HttpRequest req;
	private HttpResponse res;
	protected static HttpException notFoundHttpException;
}
